﻿using MCPlatform.MotionLib.Base;
using MCPlatform.MotionLib.Base.Models;
using System;
using System.Collections.Generic;

namespace MCPlatform.MotionLib.Factory.LeadShine
{
    public class LTMotion : IMotion
    {
        protected NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();//打印日志
        public  ushort MotionID { get { return this._axisNo; } set { this._axisNo = value; StartUp(); } }      
        private ushort _cardNo = 0;
        private ushort _axisNo;
        private double _equiv;
        private int _plimit;
        private int _nlimit;
        private double _position;
        private double _velocity;

        private MotionParaModel _axisParaModel = new MotionParaModel();
        private bool _isPause;

        public MotionParaModel AxisConfig 
        { 
            get { return _axisParaModel; } 
            set { _axisParaModel = value; } 
        }

        /// <summary>
        /// 脉冲当量设置，使能之前使用
        /// Equiv 为100，则发送定位指令100代表1mm，也就是1代表0.01mm,速度单位为mm/s
        /// Equiv 为1，则定位指令发1代表1pulse，速度单位pulse/s
        /// </summary>
        public double Equiv
        {
            get
            {
                try
                {
                    logger.Info($"执行：LTDMC.dmc_get_equiv,卡号：{_cardNo}，轴号：{_axisNo} 当量：{_equiv}");
                    LTDMC.dmc_get_equiv(_cardNo, _axisNo, ref _equiv);
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + $"LTDMC.dmc_get_equiv卡号：{_cardNo}，轴号：{_axisNo} 当量：{_equiv}" + ex.Message);

                    throw new Exception("命令：" + "LTDMC.dmc_get_equiv" + ex.Message + "堆栈: " + ex.StackTrace);
                }
                return _equiv;
            }
            set
            {
                _equiv = value;
                try
                {
                    logger.Info($"执行：LTDMC.dmc_set_equiv 卡号：{_cardNo}，轴号：{_axisNo} 当量：{_equiv}");
                    LTDMC.dmc_set_equiv(_cardNo, _axisNo, _equiv);
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + $"LTDMC.dmc_set_equiv 卡号：{_cardNo}，轴号：{_axisNo} 当量：{_equiv}" + ex.Message);

                    throw new Exception("命令：" + "LTDMC.dmc_set_equiv" + ex.Message + "堆栈: " + ex.StackTrace);
                }
            }
        }

        /// <summary>
        /// 设置正负软限位
        /// </summary>
        public int PLimit
        {
            get
            {
                try
                {
                    logger.Info($"执行：LTDMC.dmc_get_softlimit 卡号：{_cardNo}，轴号：{_axisNo}，正限位{_plimit}，负限位{_nlimit}");
                    ushort enable = 0;
                    ushort source_sel = 0;
                    ushort sl_action = 0;
                    LTDMC.dmc_get_softlimit(_cardNo, _axisNo, ref enable, ref source_sel, ref sl_action, ref _nlimit, ref _plimit);
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + $" LTDMC.dmc_get_softlimit 卡号：{_cardNo}，轴号：{_axisNo}，正限位{_plimit}，负限位{_nlimit}" + ex.Message);

                    throw new Exception("命令：" + " LTDMC.dmc_get_softlimit" + ex.Message + "堆栈: " + ex.StackTrace);
                }
                return _plimit;
            }
            set
            {
                this._plimit = value;
                try
                {
                    logger.Info("执行：LTDMC.dmc_set_softlimit");
                    LTDMC.dmc_set_softlimit(_cardNo, _axisNo, 1, 0, 0, _nlimit, _plimit);
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + "  LTDMC.dmc_set_softlimit" + ex.Message);
                    throw new Exception("命令：" + " LTDMC.dmc_set_softlimit" + ex.Message + "堆栈: " + ex.StackTrace);
                }
            }

        }

        public int NLimit
        {
            get
            {
                try
                {
                    logger.Info($"执行：LTDMC.dmc_get_softlimit 卡号：{_cardNo}，轴号：{_axisNo}，正限位{_plimit}，负限位{_nlimit}");
                    ushort enalbe = 0;
                    ushort source_sel = 0;
                    ushort sl_action = 0;
                    LTDMC.dmc_get_softlimit(_cardNo, _axisNo, ref enalbe, ref source_sel, ref sl_action, ref _nlimit, ref _plimit);
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + $" LTDMC.dmc_get_softlimit 卡号：{_cardNo}，轴号：{_axisNo}，正限位{_plimit}，负限位{_nlimit}" + ex.Message);
                    throw new Exception("命令：" + " LTDMC.dmc_get_softlimit" + ex.Message + "堆栈: " + ex.StackTrace);
                }
                return _nlimit;
            }
            set
            {
                this._nlimit = value;
                try
                {
                    logger.Info("执行：LTDMC.dmc_set_softlimit");
                    LTDMC.dmc_set_softlimit(_cardNo, _axisNo, 1, 0, 0, _nlimit, _plimit);
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + " LTDMC.dmc_set_softlimit" + ex.Message);
                    throw new Exception("命令：" + "LTDMC.dmc_set_softlimit" + ex.Message + "堆栈: " + ex.StackTrace);
                }
            }
        }

        public  double ActualPosition
        {
            get
            {
                try
                {
                   // logger.Info("执行： LTDMC.dmc_get_position_unit");
                    LTDMC.dmc_get_position_unit(_cardNo, _axisNo, ref _position);
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + " LTDMC.dmc_get_position_unit" + ex.Message);
                    throw new Exception("命令：" + "LTDMC.dmc_get_position_unit" + ex.Message + "堆栈: " + ex.StackTrace);
                }
                return _position;
            }
            set
            {
                _position = value;
                try
                {
                    logger.Info("执行： LTDMC.dmc_set_position_unit");
                    LTDMC.dmc_set_position_unit(_cardNo, _axisNo, _position);
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + "LTDMC.dmc_set_position_unit" + ex.Message);
                    throw new Exception("命令：" + "LTDMC.dmc_set_position_unit" + ex.Message + "堆栈: " + ex.StackTrace);
                }

            }
        }
        public  double ActualVelocity
        {
            get
            {
                try
                {
                   // logger.Info("执行：  LTDMC.dmc_read_current_speed_unit");
                    LTDMC.dmc_read_current_speed_unit(_cardNo, _axisNo, ref _velocity);
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + "LTDMC.dmc_read_current_speed_unit" + ex.Message);
                    throw new Exception("命令：" + "LTDMC.dmc_read_current_speed_unit" + ex.Message + "堆栈: " + ex.StackTrace);
                }
                return _velocity;
            }

        }

        public double TargetPositon { get; private set; }

        public ushort RunMode { get; private set; }

        public double GetVelocity { get; set; }

        public  bool IsDone
        {
            get
            {
                try
                {
                   // logger.Info("执行：  LTDMC.dmc_check_done");
                    short result = LTDMC.dmc_check_done(_cardNo, _axisNo);

                    double pos = 0;
                    LTDMC.dmc_get_target_position_unit(_cardNo, _axisNo, ref pos);
                    if (Math.Abs(pos - this.ActualPosition) < 0.01 && result > 0)
                    {
                        return true;
                    }
                    return false;
                   // return result > 0 ? true : false;
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + "LTDMC.dmc_check_done" + ex.Message);
                    throw new Exception("命令：" + "LTDMC.dmc_check_done" + ex.Message + "堆栈: " + ex.StackTrace);
                }

            }

        }

        public bool IsHomeDone
        {
            get
            {
                try
                {
                   
                    short result = LTDMC.dmc_check_done(_cardNo, _axisNo);

                   
                    if (result > 0)
                    {
                        return true;
                    }
                    return false;
                    // return result > 0 ? true : false;
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + "LTDMC.dmc_check_done" + ex.Message);
                    throw new Exception("命令：" + "LTDMC.dmc_check_done" + ex.Message + "堆栈: " + ex.StackTrace);
                }

            }

        }
        public bool IsStop
        {
            get
            {
                try
                {
                   
                    short result = LTDMC.dmc_check_done(_cardNo, _axisNo);

                    
                    return result > 0 ? true : false;
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + "LTDMC.dmc_check_done" + ex.Message);
                    throw new Exception("命令：" + "LTDMC.dmc_check_done" + ex.Message + "堆栈: " + ex.StackTrace);
                }

            }

        }

        public bool IsEnabled 
        {
            get
            {
                try
                {
                    ushort axisState = 0;
                    short result = LTDMC.nmc_get_axis_state_machine(_cardNo, _axisNo, ref  axisState);
                    return axisState == 4 ? true : false;
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + " LTDMC.nmc_get_axis_state_machine" + ex.Message);
                    throw new Exception("命令：" + " LTDMC.nmc_get_axis_state_machine" + ex.Message + "堆栈: " + ex.StackTrace);
                }
            }
        }

        public  bool IsMoving
        {
            get
            {
                try
                {
                    
                   // logger.Info("执行：  LTDMC.dmc_get_axis_run_mode");
                    short result = LTDMC.dmc_check_done(_cardNo, _axisNo);
                    return result > 0 ? false : true;
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + " LTDMC.dmc_check_done" + ex.Message);
                    throw new Exception("命令：" + " LTDMC.dmc_check_done" + ex.Message + "堆栈: " + ex.StackTrace);
                }

            }

        }

        public  bool IsError
        {
            get
            {
                try
                {
                    //logger.Info("执行： LTDMC.nmc_get_axis_errcode");
                    ushort errorCode = 0;
                    short result = LTDMC.nmc_get_axis_errcode(_cardNo, _axisNo, ref errorCode);
                    return errorCode > 0 ? true : false;
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + "LTDMC.nmc_get_axis_errcode" + ex.Message);
                    throw new Exception("命令：" + "LTDMC.nmc_get_axis_errcode" + ex.Message + "堆栈: " + ex.StackTrace);
                }

            }
        }

        public string ControlName { get; set; } = string.Empty;

        public  ushort ErrorID
        {
            get
            {
                try
                {
                   // logger.Info("执行： LTDMC.nmc_get_axis_errcode");
                    ushort errorCode = 0;
                    short result = LTDMC.nmc_get_axis_errcode(_cardNo, _axisNo, ref errorCode);
                    return errorCode;
                }
                catch (Exception ex)
                {
                    logger.Error("命令异常：" + "LTDMC.nmc_get_axis_errcode" + ex.Message);
                    throw new Exception("命令：" + "LTDMC.nmc_get_axis_errcode" + ex.Message + "堆栈: " + ex.StackTrace);
                }

            }
        }

        public bool IsPLimit 
        {
            get 
            {
                return GetAxisStatus(1);
            }
                
        }

        public bool IsHome
        {
            get
            {
                return GetAxisStatus(4);
            }

        }

        public bool IsNLimit
        {
            get
            {
                return GetAxisStatus(2);
            }

        }

        public bool IsSPLimit
        {
            get
            {
                return GetAxisStatus(6);
            }

        }

        public bool IsEMG
        {
            get
            {
                return GetAxisStatus(3);
            }

        }

        public bool IsSNLimit
        {
            get
            {
                return GetAxisStatus(7);
            }

        }

        /// <summary>
        /// 配置轴参数
        /// </summary>
        /// <param name="cardNo"></param>
        /// <param name="axisNo"></param>
        /// <param name="homeMovePara"></param>
        /// <param name="axisProfile"></param>
        public LTMotion()

        {
            short result = LTBoard.InitBoard();
            if (result == 0)
            {
                return;
            }
            //StartUp();
        }

        public double Backlash 
        {
            get
            {
                
                double backlash = 0;
                LTDMC.dmc_get_backlash_unit(_cardNo, _axisNo,ref backlash);
                logger.Info($"轴：{_axisNo}，获取反向间隙{backlash}");
                return backlash;

            }
            set
            {
                LTDMC.dmc_set_backlash_unit(_cardNo, _axisNo,value);
                logger.Info($"轴：{_axisNo}，设置反向间隙{value}");
                
            }
        }

        /// <summary>
        /// 设置单轴速度曲线
        /// </summary>
        /// <returns>错误码</returns>
        /// <exception cref="Exception">命令异常</exception>

        public short SetProfile()
        {
            try
            {
                short result = LTDMC.dmc_set_profile_unit(_cardNo, _axisNo, AxisConfig.MinVelocity, AxisConfig.MaxVelocity,
                    AxisConfig.Acc, AxisConfig.Dec, AxisConfig.StopVelocity);
                if (result > 0) return result;
                result = LTDMC.dmc_set_s_profile(_cardNo, _axisNo, AxisConfig.SMode, AxisConfig.SPara);

                if (AxisConfig.IsEnableSoftLimit)
                {
                    PLimit = (int)AxisConfig.SPLimit;
                    NLimit = (int)AxisConfig.SNLimit;
                   
                }
                else
                {
                    LTDMC.dmc_set_softlimit(_cardNo, _axisNo, 0, 0, 0, 0, 0);
                }
               
                Backlash = AxisConfig.Backlash;
                SetHomeProfile();
                logger.Info("执行：setProfile");
                return result;
            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + "LTDMC.dmc_set_profile_unit" + ex.Message);
                throw new Exception("命令：" + "LTDMC.dmc_set_profile_unit" + ex.Message + "堆栈: " + ex.StackTrace);
            }
        }

        public short SetVelocityRate(double rate)
        {
            try
            {
                double velocity = AxisConfig.MaxVelocity * rate;
                SetVelocity(velocity);
                return ChangeVelocity(velocity);
              //  return SetVelocity(velocity);
            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + "LTDMC.dmc_set_profile_unit" + ex.Message);
                throw new Exception("命令：" + "LTDMC.dmc_set_profile_unit" + ex.Message + "堆栈: " + ex.StackTrace);
            }

        }
        public  short SetVelocity(double velocity)
        {
            try
            {
                GetVelocity = velocity;
                short result = LTDMC.dmc_set_profile_unit(_cardNo, _axisNo, AxisConfig.MinVelocity, velocity,
                    AxisConfig.Acc, AxisConfig.Dec, AxisConfig.StopVelocity);
                if (result > 0) return result;
                result = LTDMC.dmc_set_s_profile(_cardNo, _axisNo, AxisConfig.SMode, AxisConfig.SPara);
                logger.Info("执行：setProfile");
                return result;
            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + "LTDMC.dmc_set_profile_unit" + ex.Message);
                throw new Exception("命令：" + "LTDMC.dmc_set_profile_unit" + ex.Message + "堆栈: " + ex.StackTrace);
            }
        
        }

        /// <summary>
        /// 在线变速
        /// </summary>
        /// <param name="velocity">新的速度</param>
        /// <param name="tAccDec">加减速时间</param>
        /// <returns>错误码</returns>
        /// <exception cref="Exception"></exception>
        public short ChangeVelocity(double velocity,double tAccDec=0.05)
        {
            try
            {
                logger.Info($"执行：dmc_change_speed_unit,速度{velocity}，加减速时间{tAccDec}");
                GetVelocity = velocity;
                return LTDMC.dmc_change_speed_unit(_cardNo, _axisNo, velocity, AxisConfig.Acc);
                            
            }
            catch (Exception ex)
            {
                logger.Error($"执行：dmc_change_speed_unit,速度{velocity}，加减速时间{tAccDec}");
                throw new Exception("命令：" + "LTDMC.dmc_change_speed_unit" + ex.Message + "堆栈: " + ex.StackTrace);
            }

        }


        /// <summary>
        /// 轴使能，轴号为255代表全部EtherCAT轴使能
        /// </summary>
        /// <returns>错误码</returns>
        /// <exception cref="Exception">命令异常</exception>
        public  short Enable()
        {
            try
            {
                logger.Info($"轴:{ControlName},执行：enable");
                return LTDMC.nmc_set_axis_enable(_cardNo, _axisNo);
            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + "LTDMC.nmc_set_axis_enable" + ex.Message);
                throw new Exception("命令：" + "LTDMC.nmc_set_axis_enable" + ex.Message + "堆栈: " + ex.StackTrace);
            }
        }

        /// <summary>
        /// 轴断使能
        /// 轴号为255代表断掉全部EtherCAT总线轴
        /// </summary>
        /// <returns>错误码</returns>
        /// <exception cref="Exception">命令异常</exception>
        public  short Disable()
        {
            try
            {
                logger.Info($"轴:{ControlName},执行：Disable");
                return LTDMC.nmc_set_axis_disable(_cardNo, _axisNo);
            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + " LTDMC.nmc_set_axis_disable" + ex.Message);
                throw new Exception("命令：" + "LTDMC.nmc_set_axis_disable" + ex.Message + "堆栈: " + ex.StackTrace);
            }
        }

        /// <summary>
        /// 绝对定位运动
        /// 最后一个参数，0相对运动，1绝对运动
        /// </summary>
        /// <param name="Dist">定位坐标</param>
        /// <returns>成功返回0，否则是其他错误代码</returns>
        public  short AbsMove(double Dist)
        {
            try
            {
                logger.Info($"轴:{ControlName},执行：AbsMove,卡号：{_cardNo}，轴号：{_axisNo}，速度：{AxisConfig.MaxVelocity}，绝对坐标：{Dist}");
                return LTDMC.dmc_pmove_unit(_cardNo, _axisNo, Dist, 1);
            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + $"LTDMC.dmc_pmove_unit 轴:{ControlName}, 卡号：{_cardNo}，轴号：{_axisNo}，速度：{AxisConfig.MaxVelocity}，绝对坐标：{Dist}" + ex.Message);
                throw new Exception("命令：" + "LTDMC.dmc_pmove_unit" + ex.Message + "堆栈: " + ex.StackTrace);
            }

        }

        /// <summary>
        /// 设置主从轴耦合参数
        ///1. 龙门功能允许一对一关系，即一个主轴对应一个从轴，允许多对一，即多个从轴一个主轴，不允许一个从轴多个主轴；
        ///2.龙门模式的跟随轴没有硬限位和软限位，主轴遇到限位停止时，跟随轴同样停止；
        ///3.如果某个轴被设置为龙门模式的跟随轴后，check done 返回一直是运动状态，直 至解除该从轴与主轴龙门关系；
        ///4.龙门函数调用有先后顺序区分，先调用 dmc_set_gear_follow_profile 建立龙门关系，再 dmc_set_grant_error_protect 设置龙门保护误差，不可对调设置顺序，否则会报错；
        ///5.龙门模式下从轴不支持螺距补偿功能
        /// </summary>
        /// <param name="slaveAxisId">从轴轴号</param>
        /// <param name="enable">使能状态</param>
        /// <returns>错误代码</returns>
        /// <exception cref="Exception"></exception>
        public short SetGearFollow(ushort slaveAxisId,bool enable)
        {
            try
            {
                logger.Info($"轴:{ControlName},执行：龙门耦合,卡号：{_cardNo}，主轴号：{_axisNo}，从轴号：{slaveAxisId}，使能状态：{enable}");
                ushort uEnable =(ushort)( enable ? 1 : 0);
                return LTDMC.dmc_set_gear_follow_profile(_cardNo, slaveAxisId, uEnable, _axisNo, 1);
            }
            catch (Exception ex)
            {
                logger.Error($"轴:{ControlName},执行：龙门耦合,卡号：{_cardNo}，主轴号：{_axisNo}，从轴号：{slaveAxisId}，使能状态：{enable}");
                throw new Exception("命令：" + "LTDMC.dmc_set_gear_follow_profile" + ex.Message + "堆栈: " + ex.StackTrace);
            }
        }


        /// <summary>
        /// 读取耦合的主轴ID
        /// </summary>
        /// <param name="masterAxisId">主轴ID</param>
        /// <param name="enable">使能</param>
        /// <returns>错误码</returns>
        /// <exception cref="Exception"></exception>
        public short GetGearFollow(ref ushort masterAxisId,ref bool enable)
        {
            try
            {               
                ushort uEnable = 0;
                double ratio = 1;
                var res =  LTDMC.dmc_get_gear_follow_profile(_cardNo, _axisNo,ref uEnable,ref masterAxisId, ref ratio);
                enable = uEnable > 0 ? true : false;
                logger.Info($"轴:{ControlName},执行：读取龙门耦合,卡号：{_cardNo}，从轴号：{_axisNo}，主轴号：{masterAxisId}，使能状态：{enable}");
                return res;
            }
            catch (Exception ex)
            {
                logger.Error($"轴:{ControlName},执行：读取龙门耦合,卡号：{_cardNo}，从轴号：{_axisNo}，主轴号：{masterAxisId}，使能状态：{enable}");
                throw new Exception("命令：" + "LTDMC.dmc_get_gear_follow_profile" + ex.Message + "堆栈: " + ex.StackTrace);
            }
        }


        /// <summary>
        /// 设置跟随误差停止阈值
        /// </summary>
        /// <param name="enable">使能状态</param>
        /// <param name="dstpError">减速停止误差</param>
        /// <param name="emgError">立即停止误差</param>
        /// <returns>错误码</returns>
        /// <exception cref="Exception"></exception>
        public short SetGrantError(bool enable,double dstpError,double emgError)
        {
            try
            {
                logger.Info($"轴:{ControlName},执行：设置跟随误差停止阈值,卡号：{_cardNo}，轴号：{_axisNo}，使能状态：{enable}，减速停止误差：{dstpError}，立即停止误差：{emgError}");
                ushort uEnable = (ushort)(enable ? 1 : 0);
                return LTDMC.dmc_set_grant_error_protect_unit(_cardNo, _axisNo, uEnable, dstpError, emgError);
            }
            catch (Exception ex)
            {
                logger.Error($"轴:{ControlName},执行：设置跟随误差停止阈值,卡号：{_cardNo}，轴号：{_axisNo}，使能状态：{enable}，减速停止误差：{dstpError}，立即停止误差：{emgError}");
                throw new Exception("命令：" + "LTDMC.dmc_set_grant_error_protect_unit" + ex.Message + "堆栈: " + ex.StackTrace);
            }
        }

        /// <summary>
        /// 读取跟随误差停止阈值
        /// </summary>
        /// <param name="enable">使能状态</param>
        /// <param name="dstpError">减速停止误差</param>
        /// <param name="emgError">立即停止误差</param>
        /// <returns>错误码</returns>
        /// <exception cref="Exception"></exception>
        public short GetGrantError(ref bool enable,ref double dstpError,ref double emgError)
        {
            try
            {
                ushort uEnable = 0;              
                var res = LTDMC.dmc_get_grant_error_protect_unit(_cardNo, _axisNo, ref uEnable, ref dstpError, ref emgError);
                enable = uEnable > 0 ? true : false;
                logger.Info($"轴:{ControlName},执行：读取跟随误差停止阈值,卡号：{_cardNo}，轴号：{_axisNo}，使能状态：{enable}，减速停止误差：{dstpError}，立即停止误差：{emgError}");
                return res;
            }
            catch (Exception ex)
            {
                logger.Error($"轴:{ControlName},执行：读取跟随误差停止阈值,卡号：{_cardNo}，轴号：{_axisNo}，使能状态：{enable}，减速停止误差：{dstpError}，立即停止误差：{emgError}");
                throw new Exception("命令：" + "LTDMC.dmc_get_grant_error_protect_unit" + ex.Message + "堆栈: " + ex.StackTrace);
            }
        }

       


        /// <summary>
        /// EtherCAT 总线回原
        /// 1.先设置回原参数
        /// 2.启动回原
        /// 3.等待回原完成
        /// </summary>
        /// <param name="HomingMode">回原模式</param>
        /// <returns></returns>
        public  short HomeMove()
        {
            ushort Result = 0;
            try
            {
                short rst = LTDMC.nmc_set_home_profile(_cardNo, _axisNo,
                     AxisConfig.HomingMode, AxisConfig.HomingLowerVelocity, AxisConfig.HomingHeightVelocity,
                     AxisConfig.Acc, AxisConfig.Dec, AxisConfig.HomingOffSet);
                if (rst > 0) { return rst; }
                rst = LTDMC.nmc_home_move(_cardNo, _axisNo);
                if (rst > 0) { return rst; }
                rst = LTDMC.dmc_get_home_result(_cardNo, _axisNo, ref Result);
                if (rst > 0) { return rst; }
                logger.Info($"轴:{ControlName},执行：HomeMove 卡号：{_cardNo}，轴号：{_axisNo}，回原模式：{AxisConfig.HomingMode}，回原速度：{AxisConfig.HomingHeightVelocity}");
                return (short)Result;
            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + $"LTDMC.nmc_set_home_profile 轴:{ControlName}, 卡号：{_cardNo}，轴号：{_axisNo}，回原模式：{AxisConfig.HomingMode}，回原速度：{AxisConfig.HomingHeightVelocity}" + ex.Message);
                throw new Exception("命令：" + "LTDMC.nmc_set_home_profile" + ex.Message + "堆栈: " + ex.StackTrace);

            }
        }

        public  short SetHomeVel(double Velocity)
        {

            try
            {
                return LTDMC.nmc_set_home_profile(_cardNo, _axisNo,
                      AxisConfig.HomingMode, AxisConfig.HomingLowerVelocity, Velocity,
                      AxisConfig.Acc, AxisConfig.Dec, AxisConfig.HomingOffSet);

            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + "LTDMC.nmc_set_home_profile" + ex.Message);
                throw new Exception("命令：" + "LTDMC.nmc_set_home_profile" + ex.Message + "堆栈: " + ex.StackTrace);

            }
        }

        public short SetHomeProfile()
        {

            try
            {
                return LTDMC.nmc_set_home_profile(_cardNo, _axisNo,
                      AxisConfig.HomingMode, AxisConfig.HomingLowerVelocity, AxisConfig.HomingHeightVelocity,
                      AxisConfig.Acc, AxisConfig.Dec, AxisConfig.HomingOffSet);

            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + "LTDMC.nmc_set_home_profile" + ex.Message);
                throw new Exception("命令：" + "LTDMC.nmc_set_home_profile" + ex.Message + "堆栈: " + ex.StackTrace);

            }
        }
        /// <summary>
        /// 点动模式
        /// 记得调用完成停止轴
        /// </summary>
        /// <param name="dir">0负方向，1正方向</param>
        /// <returns></returns>
        public  short Jog(ushort dir)
        {
            try
            {
                logger.Info($"轴:{ControlName},执行：Jog，卡号：{_cardNo}，轴号：{_axisNo}，速度：{AxisConfig.MaxVelocity}");
                return LTDMC.dmc_vmove(_cardNo, _axisNo, dir);
            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" +$"LTDMC.dmc_vmove 轴:{ControlName},卡号：{_cardNo}，轴号：{_axisNo}，速度：{AxisConfig.MaxVelocity}" + ex.Message);

                throw new Exception("命令：" + "LTDMC.dmc_vmove" + ex.Message + "堆栈: " + ex.StackTrace);
            }
        }

        /// <summary>
        /// 相对运动，也就是寸动
        /// 最后一个参数，1是绝对运动，0是相对运动
        /// </summary>
        /// <param name="RelDist">寸动距离</param>
        /// <returns></returns>
        public  short RelMove(double RelDist)
        {
            try
            {
                logger.Info($"轴:{ControlName},执行：RelMove,，卡号：{_cardNo}，轴号：{_axisNo}，速度：{AxisConfig.MaxVelocity},相对距离：{RelDist}");
                return LTDMC.dmc_pmove_unit(_cardNo, _axisNo, RelDist, 0);
            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + $"LTDMC.dmc_pmove_unit 轴:{ControlName}, 卡号：{_cardNo}，轴号：{_axisNo}，速度：{AxisConfig.MaxVelocity},相对距离：{RelDist}" + ex.Message);

                throw new Exception("命令：" + "LTDMC.dmc_pmove_unit" + ex.Message + "堆栈: " + ex.StackTrace);
            }

        }

        /// <summary>
        /// 停止单轴
        /// 最后一个参数stopMode:0 减速停止，1紧急停止
        /// </summary>
        /// <returns>返回值非零是其他错误代码</returns>
        public  short StopMove()
        {
            try
            {
                logger.Info($"轴:{ControlName},执行：StopMove 卡号：{_cardNo}，轴号：{_axisNo}");
                return LTDMC.dmc_stop(_cardNo, _axisNo, 0);
            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + $" LTDMC.dmc_stop 轴:{ControlName}, 卡号：{_cardNo}，轴号：{_axisNo}" + ex.Message);

                throw new Exception("命令：" + " LTDMC.dmc_stop" + ex.Message + "堆栈: " + ex.StackTrace);
            }

        }

        /// <summary>
        /// 急停，卡号内所有轴都紧急停止
        /// </summary>
        /// <returns>错误码</returns>
        public  short Estop()
        {
            try
            {
                logger.Error($"轴:{ControlName},执行：Estop");
                return LTDMC.dmc_emg_stop(_cardNo);
            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + "LTDMC.dmc_emg_stop" + ex.Message);

                throw new Exception("命令：" + "LTDMC.dmc_emg_stop" + ex.Message + "堆栈: " + ex.StackTrace);
            }

        }

        public  short Reset()
        {
            try
            {
                logger.Info($"轴:{ControlName},执行：Reset");
                return LTDMC.nmc_clear_axis_errcode(_cardNo, _axisNo);
            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + " LTDMC.nmc_clear_axis_errcode" + ex.Message);

                throw new Exception("命令：" + " LTDMC.nmc_clear_axis_errcode" + ex.Message + "堆栈: " + ex.StackTrace);
            }
        }

        /// <summary>
        /// 查询轴的IO状态
        /// </summary>
        /// <returns>
        /// 0 ALM 1：表示伺服报警信号 ALM 为 ON； 0：OFF
        ///1 EL+ 1：表示正硬限位信号 +EL 为 ON； 0：OFF
        ///2 EL- 1：表示负硬限位信号–EL 为 ON； 0：OFF
        ///3 EMG 1：表示急停信号 EMG 为 ON； 0：OFF
        ///4 ORG 1：表示原点信号 ORG 为 ON； 0：OFF
        ///6 SL+ 1：表示正软限位信号+SL 为 ON； 0：OFF
        ///7 SL- 1：表示负软件限位信号-SL 为 ON； 0：OFF</returns>
        /// <exception cref="Exception">命令异常</exception>

        public  uint CheckAxisStatus()
        {
            try
            {
              //  logger.Info("执行：CheckAxisStatus");
                return LTDMC.dmc_axis_io_status(_cardNo, _axisNo);
            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + " LTDMC.dmc_axis_io_status" + ex.Message);

                throw new Exception("命令：" + " LTDMC.dmc_axis_io_status" + ex.Message + "堆栈: " + ex.StackTrace);
            }
        }

        private bool GetAxisStatus(ushort index)
        {
            uint result = CheckAxisStatus();
            uint mask = (uint)(1 << index);
            return (result & mask) != 0;
        }
        private void StartUp()
        {
            SetProfile();
            SetHomeProfile();
            Equiv = AxisConfig.Equiv;
            //PLimit = (int)AxisConfig.SPLimit;
            //NLimit = (int)AxisConfig.SNLimit;

        }


        public void PauseMove()
        {
            try
            {
                _isPause = true;
                ushort runMode = 0;
                LTDMC.dmc_get_axis_run_mode(_cardNo, _axisNo, ref runMode);

                RunMode = runMode;

                double pos = this.ActualPosition;
                LTDMC.dmc_get_target_position_unit(_cardNo, _axisNo, ref pos);

                logger.Info($"轴:{ControlName},执行：暂停，运行模式{runMode}，卡号：{_cardNo}，轴号：{_axisNo}，速度：{AxisConfig.MaxVelocity}mm/s,目标位置{pos}mm");

                TargetPositon = pos;

                //连续插补模式不能直接停止，有专用的暂停指令
                if (runMode==10)
                {
                    return;
                }
                this.StopMove();

            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + $"LTDMC.dmc_get_axis_run_mode 或者 dmc_get_target_position_unit, 轴:{ControlName},卡号：{_cardNo}，轴号：{_axisNo}，速度：{AxisConfig.MaxVelocity}" + ex.Message);

                throw new Exception("命令：" + "LTDMC.dmc_get_axis_run_mode" + ex.Message + "堆栈: " + ex.StackTrace);
            }
        }

        public async Task Resume(CancellationToken cancellationToken)
        {
            try
            {
                logger.Info($"轴:{ControlName},执行：暂停恢复，运行模式{RunMode}，卡号：{_cardNo}，轴号：{_axisNo}，速度：{AxisConfig.MaxVelocity}mm/s,目标位置{TargetPositon}mm");
                _isPause = false;
                if (RunMode == 1)
                {
                    await this.AbsMoveAsync(TargetPositon, cancellationToken);
                }
                else if (RunMode == 2)
                {
                    ;
                }
                else if (RunMode == 3)
                {
                    await HomeMoveAsync(cancellationToken);
                }

            }
            catch (Exception ex)
            {
                logger.Error("命令异常：" + $"恢复运行, 轴:{ControlName},卡号：{_cardNo}，轴号：{_axisNo}，速度：{AxisConfig.MaxVelocity}" + ex.Message);

                throw new Exception("命令：" + "恢复运行" + ex.Message + "堆栈: " + ex.StackTrace);
            }
        }


        public async Task<(bool, short,string)> AbsMoveAsync(double pos)
        {
            (bool, short, string) result = (true, 0, "Done");
            if (IsMoving)
            {
                return (false, 0, "Axis is Busy");
            }

            var res = AbsMove(pos);
            if (res != 0)
            {
               return (false, res, "Abs Move Error");
            }
            await Task.Run(async () => 
            {                           
                while (IsMoving && !IsDone)
                {
                    await Task.Delay(10);
                    if (IsError)
                    {
                        result = (false, (short)ErrorID, $"{AxisConfig.ControlName}is Error");
                        break;
                    }
                    
                }
            });

            return result;
        }

        public async Task<(bool, short, string)> AbsMoveAsync(double pos,CancellationToken cancellationToken, ManualResetEvent manualResetEvent)
        {
            (bool, short, string) result = (true, 0, "Done");
            if (IsMoving)
            {
                return (false, 0, "Axis is Busy");
            }

            var res = AbsMove(pos);
            if (res != 0)
            {
                return (false, res, "Abs Move Error");
            }
            await Task.Run(async () =>
            {
                try
                {
                    

                    while (!IsDone && !cancellationToken.IsCancellationRequested)
                    {
                        manualResetEvent.WaitOne();
                         await Task.Delay(0, cancellationToken);
                        if (IsError)
                        {
                            result = (false, (short)ErrorID, $"{AxisConfig.ControlName}is Error");
                            break;
                        }
                        

                        //cancellationToken.ThrowIfCancellationRequested();
                       
                    }
                }
                catch (Exception)
                {

                    throw;
                }
                
            });

            return result;
        }


        public async Task<(bool, short, string)> AbsMoveAsync(double pos, CancellationToken cancellationToken )
        {
            (bool, short, string) result = (true, 0, "Done");
            if (IsMoving)
            {
                return (false, 0, "Axis is Busy");
            }

            var res = AbsMove(pos);
            if (res != 0)
            {
                return (false, res, "Abs Move Error");
            }
            await Task.Run(async () =>
            {
                try
                {


                    while (!IsStop && !IsDone && !cancellationToken.IsCancellationRequested)
                    {
                       
                        await Task.Delay(0, cancellationToken);
                        if (IsError)
                        {
                            result = (false, (short)ErrorID,$"{AxisConfig.ControlName}is Error");
                            break;
                        }


                        //cancellationToken.ThrowIfCancellationRequested();

                    }
                }
                catch (Exception)
                {

                    throw;
                }

            });

            return result;
        }

        public async Task<(bool, short, string)> HomeMoveAsync(CancellationToken cancellationToken, ManualResetEvent manualResetEvent)
        {
            (bool, short, string) result = (true, 0, "Done");
            if (IsMoving)
            {
                return (false, 0, "Axis is Busy");
            }

            var res = HomeMove();
            if (res != 0)
            {
                return (false, res, "Home Move Error");
            }
            await Task.Run(async () =>
            {
                while (!IsHomeDone && !cancellationToken.IsCancellationRequested)
                {
                    manualResetEvent.WaitOne();
                    await Task.Delay(10);
                    if (IsError)
                    {
                        result = (false, (short)ErrorID, $"{AxisConfig.ControlName}is Error");
                        break;
                    }

                }
            });

            return result;
        }

        public async Task<(bool, short, string)> HomeMoveAsync(CancellationToken cancellationToken)
        {
            (bool, short, string) result = (true, 0, "Done");
            if (IsMoving)
            {
                return (false, 0, "Axis is Busy");
            }

            var res = HomeMove();
            if (res != 0)
            {
                return (false, res, "Home Move Error");
            }
            await Task.Run(async () =>
            {
                while (!IsStop && !IsHomeDone && !cancellationToken.IsCancellationRequested)
                {
                   
                    await Task.Delay(10);
                    if (IsError)
                    {
                        result = (false, (short)ErrorID, $"{AxisConfig.ControlName}is Error");
                        break;
                    }

                }
            });

            return result;
        }

        public async Task<(bool, short, string)> RelMoveAsync(double dist, CancellationToken cancellationToken, ManualResetEvent manualResetEvent)
        {
            (bool, short, string) result = (true, 0, "Done");
            if (IsMoving)
            {
                return (false, 0, "Axis is Busy");
            }

            var res = RelMove(dist);
            if (res != 0)
            {
                return (false, res, "Abs Move Error");
            }
            await Task.Run(async () =>
            {
                while (!IsDone && !cancellationToken.IsCancellationRequested)
                {
                    manualResetEvent.WaitOne();
                    await Task.Delay(10);
                    if (IsError)
                    {
                        result = (false, (short)ErrorID, $"{AxisConfig.ControlName}is Error");
                        break;
                    }

                }
            });

            return result;
        }


        
    }
}
